#include "RawSocket.h"

SK

RawSocket::RawSocket (int protocol)
:protocol (protocol)
{
    WSADATA dat;

    WSAStartup (MAKEWORD (2,2), &dat);
    
    soc = ::socket (AF_INET, SOCK_RAW, protocol);

    if (soc == INVALID_SOCKET)
    {
        err = WSAGetLastError ();
    }

    BOOL val=1;
    ::setsockopt (soc, SOL_SOCKET,SO_BROADCAST, (char *)&val, sizeof (BOOL));
    ::setsockopt (soc, IPPROTO_IP,IP_HDRINCL, (char *)&val, sizeof (BOOL));
}

RawSocket::~RawSocket()
{
    ::closesocket (soc);
    
}


bool RawSocket::sendTo (byte *data, u32 length, const String& dest)
{
    sockaddr_in rHost;
    rHost.sin_family = AF_INET;
    rHost.sin_port = htons(0);
    rHost.sin_addr.s_addr = inet_addr (dest.c_str());

    int ret = ::sendto (soc, (char *)data, length, 0,(sockaddr *)&rHost, sizeof (sockaddr_in));
    err = WSAGetLastError ();
    return ret > 0;
}

int RawSocket::recvFrom (byte *buf, u32 bufSize, const String& from)
{
    sockaddr_in adr;
    adr.sin_addr.s_addr = inet_addr (from.c_str());
    adr.sin_family = AF_INET;
    adr.sin_port = htons(0);
    int fromLen = sizeof (adr);
    int ret = ::recvfrom (soc, (char *)buf, bufSize, 0, (sockaddr *)&adr, &fromLen);  

    if (ret == -1)
        err = WSAGetLastError ();

    return ret;
}


u16 RawSocket::calculateIPChecksum(byte *packet, int len)
{
    register int sum = 0;
    u_short answer = 0;
    register u_short *w = (u16 *)packet;
    register int nleft = len;
    while (nleft > 1)
    {
      sum += *w++;
      nleft -= 2;
    }

    if (nleft == 1)
    {
      *(u_char *) (&answer) = *(u_char *) w;
      sum += answer;
    }

    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);
    answer = ~sum;
    return (answer);
}

EK